import os
import time

from paramiko import SSHClient, AutoAddPolicy
from scp import SCPClient
import sys

machine_info = [
    {
        'hostname': '192.168.10.28',
        'username': 'finance',
        'password': 'finance',
        'workdir': '/home/finance/apollo/apollo-app/apollo',
        'member_id': '267c90830e26493c8177c1ac8e9ed091'
    },
    {
        'hostname': '192.168.10.15',
        'username': 'hz_dev',
        'password': 'Km-9zL,2q?yU-Bv#2hP',
        'workdir': '/home/hz_dev/apollo/apollo-app/apollo',
        'member_id': '6f62614c1a4c422981ee6c07e0f45247'
    },
    {
        'hostname': '192.168.10.31',
        'username': 'finance',
        'password': 'Km-9zL,2q?yU-Bv#2hP',
        'workdir': '/home/finance/apollo/apollo-app/apollo',
        'member_id': '743fef8c611c48a69129e8a2cf4c2993'
    },
    {
        'hostname': '192.168.10.98',
        'username': 'app',
        'password': 'Nvx@123$',
        'workdir': '/home/app/apollo_v2.3.0/apollo/apollo-app/apollo',
        'member_id': 'bc87248609e14721a11fab88f7269ab7'
    },
    {
        'hostname': '192.168.10.99',
        'username': 'app',
        'password': 'Nvx@123$',
        'workdir': '/home/app/apollo_v2.3.0/apollo/apollo-app/apollo',
        'member_id': 'dce7c138a65c433f926eb42a4c12115f'
    },
]

project_dir = r"D:\project\apollo"

scp_files = [
    'kernel/components/boosting/vertboost2/vert_xgboost_promoter.py',
    'kernel/components/boosting/vertboost2/vert_xgboost_provider.py',
    'kernel/components/boosting/vertboost2/xgb_predict.py'
]

log_dir = '/home/app/log/python_service'


dst_logs = r"D:\tmp\logs"


class Transport(object):
    def __init__(self, machine):
        self.machine = machine
        self.ssh = {}
        self.connect()

        self.promoter_li = []

    @staticmethod
    def cmd_git(path):
        cmd0 = f"cd {path}"
        cmd1 = 'git checkout -- .'
        cmd2 = 'git pull'
        return ';'.join([cmd0, cmd1, cmd2])

    @staticmethod
    def cmd_docker():
        cmd1 = 'docker ps | grep apollo_python'
        return ';'.join([cmd1])

    @staticmethod
    def cmd_test():
        cmd1 = 'sudo ls'
        return ';'.join([cmd1])

    def connect(self):
        for i in self.machine:
            ssh = SSHClient()
            ssh.set_missing_host_key_policy(AutoAddPolicy())
            # ssh.load_system_host_keys()
            ssh.connect(hostname=i['hostname'], username=i['username'], password=i['password'])

            scp = SCPClient(ssh.get_transport(), progress=self.progress)
            self.ssh.update(
                {
                    i['hostname']: {
                        'ssh': ssh,
                        'workdir': i['workdir'],
                        'username': i['username'],
                        'scp': scp,
                        'member_id': i['member_id']
                    }
                }
            )

    @staticmethod
    def progress(filename, size, sent):
        sys.stdout.write("%s's progress: %.2f%%   \r" % (filename, float(sent) / float(size) * 100))


    def chanel_exe_cmd(self, chanel, cmd, pwd=None, t=0.5):
        if cmd in (pwd, "yes"):
            chanel.send(f"{cmd}\n")
        else:
            chanel.send(f"sudo echo 'ceason start'; {cmd}; echo 'ceason end'\n")
        # chanel.send("\n")

        print("Exec sshCmd: %s" % (cmd))

        flag = False
        while True:
            time.sleep(t)
            resp = chanel.recv(1024*1024).decode("utf8")
            if "ceason start" in resp and not flag:
                t = 5
                flag = True
            print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
            print(f"Exec Result: {resp}")
            print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n")
            print(len(resp))
            if "ceason end" in resp:
                break
            if len(resp) < 500:
                break

        if "password" in resp:
            self.chanel_exe_cmd(chanel, pwd, pwd)
        if "you sure you want to continue connecting" in resp:
            self.chanel_exe_cmd(chanel, "yes", pwd)


    def sync_code(self):
        work_dir = "/home/app/apollo_v2.3.0/apollo/apollo-app/apollo"
        ssh = SSHClient()
        ssh.set_missing_host_key_policy(AutoAddPolicy())
        ssh.connect(hostname="192.168.10.99", username="app", password="Nvx@123$")
        chanelSSHOb = ssh.invoke_shell()
        get_cmd = f"cd {work_dir} ; git checkout -- . ; git pull"
        self.chanel_exe_cmd(chanelSSHOb, get_cmd)

        for h in [28]:
            scp_cmd = f"sudo scp -r {work_dir} app@192.168.10.{h}:/home/app/apollo_v2.3.0/apollo/apollo-app/"
            scp_pwd = "Nvx@123$"
            self.chanel_exe_cmd(chanelSSHOb, scp_cmd, scp_pwd, 0.5)


    def close(self):
        for h, v in self.ssh.items():
            v['scp'].close()
            v['ssh'].close()

    def push(self, src, dst):
        for h, v in self.ssh.items():
            print(f"{v['username']}@{h}:{dst}")
            v['scp'].put(src, '/'.join((v['workdir'], dst)))

    def pull(self, src, dst):
        for h, v in self.ssh.items():
            v['scp'].get(src, '/'.join((v['workdir'], dst)))

    def pull_logs(self, component_id, job_id):

        for h, v in self.ssh.items():
            m_type = 'promoter' if h in self.promoter_li else 'provider'
            src = '/'.join([log_dir, job_id, m_type, v['member_id'], component_id, 'DEBUG.log'])
            dst_dir = os.path.join(dst_logs, job_id)
            self.check_dir(dst_dir)
            dst = os.path.join(dst_dir, f"{h.split('.')[-1]}_DEBUG.log")
            print(src)
            print(dst)
            v['scp'].get(src, dst)

    @staticmethod
    def check_dir(dirname):
        """
        检测目录是否存在，不存在则创建
        :param dirname:
        :return:
        """
        if not os.path.exists(dirname):
            os.makedirs(dirname)
        return dirname


if __name__ == '__main__':
    machine_info = [
        # {
        #     'hostname': '192.168.10.28',
        #     'username': 'app',
        #     'password': 'Nvx@123$',
        #     'workdir': '/home/app/apollo_v2.3.0/apollo/apollo-app/apollo',
        #     'member_id': '267c90830e26493c8177c1ac8e9ed091'
        # },
        # {
        #     'hostname': '192.168.10.15',
        #     'username': 'app',
        #     'password': 'Nvx@123$',
        #     'workdir': '/home/app/apollo_v2.3.0/apollo/apollo-app/apollo',
        #     'member_id': '6f62614c1a4c422981ee6c07e0f45247'
        # },
        {
            'hostname': '192.168.10.31',
            'username': 'app',
            'password': 'Nvx@123$',
            'workdir': '/home/app/apollo_v2.3.0/apollo/apollo-app/apollo',
            'member_id': '743fef8c611c48a69129e8a2cf4c2993'
        },
        # {
        #     'hostname': '192.168.10.98',
        #     'username': 'app',
        #     'password': 'Nvx@123$',
        #     'workdir': '/home/app/apollo_v2.3.0/apollo/apollo-app/apollo',
        #     'member_id': 'bc87248609e14721a11fab88f7269ab7'
        # },
        # {
        #     'hostname': '192.168.10.99',
        #     'username': 'app',
        #     'password': 'Nvx@123$',
        #     'workdir': '/home/app/apollo_v2.3.0/apollo/apollo-app/apollo',
        #     'member_id': 'dce7c138a65c433f926eb42a4c12115f'
        # }
    ]

    tp = Transport(machine_info)

    tp.sync_code()
    exit(34)

    tp.promoter_li.append("192.168.10.28")

    for i in tp.ssh:
        # stdin, stdout, stderr = tp.ssh[i]['ssh'].exec_command(tp.cmd_git(tp.ssh[i]['workdir']))

        # stdin, stdout, stderr = tp.ssh[i]['ssh'].exec_command(tp.cmd_test())

        # print(stdout.read().decode("utf-8"))

        chanelSSHOb = tp.ssh[i]['ssh'].invoke_shell()
        cmd = 'sudo ls'

        res = tp.chanel_exe_cmd(chanelSSHOb, cmd, 1)

        if "password for" in res:
            tp.chanel_exe_cmd(chanelSSHOb, "Nvx@123$")


    tp.close()


